#include <bondlib/BestQuote/CTakenPriceMap.h>
#include <bondlib/BondContainer.h>
#include <bondlib/CompanyReport.h>
#include <bondlib/BondCDCPriceInfo.h>
#include <core/strings/string_util.h>
#include <core/time/date.h>
#include <mutex>
#include <uam/UserAccountManager.h>
#include <uam/ServerTimeMgr.h>
#include <bondlib/BondDict.h>
#include <qbtools/tools.h>
#include <qbprotocol/include/SSQBAModel.h>
#include <bondlib/BondCSIPriceInfo.h>
#include <bondlib/QBIssuerInfo.h>
#include "../SSBizTool.h"
#include <bondlib/BondType.h>
#include <bondlib/ABSBondInfo.h>
#include "RealTimeDealSorter.h"

#define MIN_UNAUTH_VALUE -1E7		// 用于没有权限的最小双精度数
namespace{
	inline bool IsEmpty(const char* str){
		// 旧代码是 strlen(str)<=0;
		return str == NULL || *str == '\0';
	}
}

#define StringCopy qb::base::StringUtil::StringCopy

namespace detail{
	typedef RealTimeDealSorter::KeyType KeyType;
	typedef MarketStreamInfo RecordType;
	double CBondUtil::GetBuyPrice(const BrokerKey& key)
	{
		double idval = 0;
		REPORT* iRpt = GetCompanyInfoById(key.GetBrokerId(), key);
		if (strcmp(iRpt->m_bidinfo.m_sPrice, "Bid") == 0)
		{
			idval = 0.00001;
		}
		else
		{
			idval = atof(iRpt->m_bidinfo.m_sPrice);
		}

		if (strcmp(iRpt->m_bidinfo.m_price_status, "0") == 0
			|| iRpt->m_bidinfo.m_sPrice[0] == '\0')        //显示“--”
		{
			idval = MIN_VAL;
		}
		return idval;
	}

	double CBondUtil::GetSellPrice(const BrokerKey& key)
	{
		double idval = 0;
		REPORT* iRpt = GetCompanyInfoById(key.GetBrokerId(), key);
		if (strcmp(iRpt->m_askinfo.m_sPrice, "Ofr") == 0)
		{
			idval = 0.00001;
		}
		else
		{
			idval = atof(iRpt->m_askinfo.m_sPrice);
		}

		if (strcmp(iRpt->m_askinfo.m_price_status, "0") == 0
			|| iRpt->m_askinfo.m_sPrice[0] == '\0')        //显示“--”
		{
			idval = MIN_VAL;
		}
		return idval;
	}
	double CBondUtil::GetModifyTime(const BrokerKey& key)
	{
		REPORT* r1 = GetCompanyInfoById(key.GetBrokerId(), key);
		time_t maxr1 = max(r1->m_time, r1->m_create_time);
		return (double)maxr1;
	}
	REPORT* CBondUtil::GetCompanyInfoById(const std::string& szKey, const BrokerKey& szID)
	{
		static REPORT stRep;
		memset(&stRep, 0, sizeof(stRep));
		bool found = false;
		CBondCompanyRep* ptmp = CBondContainer::instance().GetCompanyRep(szID.m_nIndex);
		found = ptmp ? ptmp->GetCompanyRepByKey(szKey, stRep) : false;
		return &stRep;
	}
	namespace{
		inline double ToDashFloat(const char* str)
		{
			// 同CSSImpSortBondAllBroker中的MIN_VAL
			if (str && *str != 0)
			{
				if (str[0] == '-' && str[1] == '-')
					return MIN_VAL;
				return atof(str);
			}
			return MIN_VAL;
		}

		class RatingRankManager{
			typedef std::map<string, int> RankMap;
			bool			m_initialized;
			std::mutex		m_init_lock;
			RankMap			m_rankmap;
		public:
			static RatingRankManager& Get()
			{
				static RatingRankManager rrm; return rrm;
			}
			RatingRankManager() :m_initialized(false){}
			int GetRatingRank(const string &sRating)
			{
				if (!m_initialized)
				{
					std::lock_guard<std::mutex> locker(m_init_lock);
					if (!m_initialized)
					{
						Init();
						m_initialized = true;
					}
				}
				RankMap::const_iterator pos = m_rankmap.find(sRating);
				if (pos != m_rankmap.end())
				{
					return  pos->second;
				}
				return -1;
			}
		protected:
			void Init()
			{
				int nIndex = 0;
				m_rankmap[""] = nIndex;
				m_rankmap["--"] = nIndex;
				m_rankmap["CCL"] = nIndex++;
				m_rankmap["D"] = nIndex++;
				m_rankmap["C-3"] = nIndex++;
				m_rankmap["C-2"] = nIndex++;
				m_rankmap["C-"] = nIndex++;
				m_rankmap["C-"] = nIndex++;
				m_rankmap["C"] = nIndex++;
				m_rankmap["C+"] = nIndex++;
				m_rankmap["CC-"] = nIndex++;
				m_rankmap["CC"] = nIndex++;
				m_rankmap["CC+"] = nIndex++;
				m_rankmap["CCC-"] = nIndex++;
				m_rankmap["C-1"] = nIndex++;
				m_rankmap["CCC"] = nIndex++;
				m_rankmap["CCC+"] = nIndex++;
				m_rankmap["B-3"] = nIndex++;
				m_rankmap["B-2"] = nIndex++;
				m_rankmap["B-"] = nIndex++;
				m_rankmap["B"] = nIndex++;
				m_rankmap["B+"] = nIndex++;
				m_rankmap["BB-"] = nIndex++;
				m_rankmap["BB"] = nIndex++;
				m_rankmap["BB+"] = nIndex++;
				m_rankmap["BBB-"] = nIndex++;
				m_rankmap["B-1"] = nIndex++;
				m_rankmap["BBB"] = nIndex++;
				m_rankmap["BBB+"] = nIndex++;
				m_rankmap["A-3"] = nIndex++;
				m_rankmap["A-2"] = nIndex++;
				m_rankmap["A-"] = nIndex++;
				m_rankmap["A"] = nIndex++;
				m_rankmap["A+"] = nIndex++;
				m_rankmap["AA-"] = nIndex++;
				m_rankmap["AA2"] = nIndex++;
				m_rankmap["AA(2)"] = nIndex++;
				m_rankmap["AA"] = nIndex++;
				m_rankmap["AA+"] = nIndex++;
				m_rankmap["AAA-"] = nIndex++;
				m_rankmap["A-1"] = nIndex++;
				m_rankmap["AAA"] = nIndex++;
				m_rankmap["AAA+"] = nIndex++;//AAA+ > AAA > A-1 > AAA- > AA+ > AA > AA- > A+ > A > A- > A-2 > A-3 > BBB+ > BBB
			}
		};

	}
	class DealRecordReader : public IBondReader{
		const IRecordMap*	m_records;
		SSUserAccountManager::CDCAuthKey m_cdcauthKey;	// 一旦设定,需要下次点击重排才更新
		bool	m_hascdcrights;
	public:
		static bool IsRequireCDCAuthority(VSortKey key)
		{
			// 哪些字段需要CDC权限
			switch (key){
			case VESTBPRICEPRE:			//昨日中债估值,double
			case VESTBPRICETODAY:		//今日中债估值
			case kDuration:				//久期,double
			case kCdcCleanPrice:		//中债净价,double
			case kBid_EstPrice:			//bid-中债,double
			case kEstPrice_Ofr:			//中债-ofr,double
			case kCsi_Cdc:				//中证一中债,double
			case kDeal_Cdc:				// 成交-中债,double
				return true;
			}
			return false;
		}
		DealRecordReader() :m_records(0){}
		void SetDealRecordMap(const IRecordMap* records){ m_records = records; }
		virtual ~DealRecordReader(){}
		int GetInstitutionSortId(const char* institutionType)
		{
			static std::map<string, int> mapInstType;
			if (mapInstType.size() <= 0)
			{
				mapInstType["CGE"] = CBondContainer::InstCentr;
				mapInstType["LGE"] = CBondContainer::InstConty;
				mapInstType["PVE"] = CBondContainer::InstPrvat;
				mapInstType["OTE"] = CBondContainer::InstOther;
			}

			BondDict dict_item_i;
			CBondDict::instance().GetBondDict("institution_subtype", institutionType, dict_item_i);
			int nSort1;
			std::map<string, int>::iterator itr1 = mapInstType.find(dict_item_i.selective_code);
			if (itr1 == mapInstType.end())
				nSort1 = CBondContainer::InstOther + 1;
			else
				nSort1 = itr1->second;
			return nSort1;
		}
		static int CalMaturityTerm(const std::string &sPrePeriod)
		{//用于期限排序
			string sPeriod = sPrePeriod;
			if (sPeriod.empty())
				return -1;

			size_t pos = sPeriod.find("+");
			if (pos >= 2)
				sPeriod = sPeriod.substr(0, pos - 1);
			if (sPeriod[sPeriod.length() - 1] == 'Y' || sPeriod[sPeriod.length() - 1] == 'y')
			{
				return atof(sPeriod.substr(0, sPeriod.length() - 1).c_str()) * 365;
			}
			else if (sPeriod[sPeriod.length() - 1] == 'M' || sPeriod[sPeriod.length() - 1] == 'm')
			{
				return atof(sPeriod.substr(0, sPeriod.length() - 1).c_str()) * 30;
			}
			else if (sPeriod[sPeriod.length() - 1] == 'W' || sPeriod[sPeriod.length() - 1] == 'w')
			{
				return atof(sPeriod.substr(0, sPeriod.length() - 1).c_str()) * 7;
			}
			else if (sPeriod[sPeriod.length() - 1] == 'D' || sPeriod[sPeriod.length() - 1] == 'd')
			{
				return atof(sPeriod.substr(0, sPeriod.length() - 1).c_str());
			}
			else
				return -999;
		}
		static IssuePeriod GetIssuePeriodSortId(int bid)
		{
			const char* strDate_1 = GetBond(bid).GetIssueStartDate();
			int iDate_1 = strDate_1 == NULL ? 0 : atoi(strDate_1);
			//2016/07/27,bushion.xin:发行时间列排序为今日>非今日（今日之前）>非今日（今日之后）>issue_period有值>--
			int nAscend_1 = 0;//今日:8;非今日（今日之前）:6;非今日（今日之后）:4;issue_period有值:2;--:0
			bool bIssuePeriod1 = false;

			//判断今日及今日之后，之前
			time_t tTime = ServerTimeMgr::instance().serverTime();
			int nToday = qb::base::IntDate::timeToInt(tTime);

			if (iDate_1 == nToday)
			{
				nAscend_1 = 8;
			}
			else if (iDate_1 > nToday)
			{
				nAscend_1 = 4;
			}
			else if (iDate_1 > 0 && iDate_1 < nToday)
			{
				nAscend_1 = 6;
			}

			if (!IsEmpty(GetBond(bid).GetIssuePeriod()))
			{
				bIssuePeriod1 = true;
				nAscend_1 = 2;
			}
			if (bIssuePeriod1)
			{
				iDate_1 = 0;
			}
			IssuePeriod ip; ip.nAscend = nAscend_1; ip.nDate = iDate_1; ip.nBondIndex = bid;
			return ip;
		}

		void FormatPrice(QString& strTemp, const char* ctPrice)
		{
			if (ctPrice[0] == '\0')
			{
				strTemp = "--";
			}
			else
			{
				strTemp = SSTools::FormatePrice(ctPrice);
			}
		}
		double ToLineFloat(const string& f1)
		{
			return (f1.empty() || f1 == "--") ? MIN_VAL : atof(f1.c_str());
		}

		double GetTknPrice(const MarketStreamType2Body& body)
		{
			/*
				原始代码,要调用ToLineFloat(GetCleanPriceStr(body));
				性能低下
				经过分析,其返回结果与以下逻辑相同
				并且,此文件中返回值,只是用来作为对两条成交记录进行比较,而不是显示			
			*/
			if (atoi(body.m_rebate) != 1)
				return IsEmpty(body.m_price) ? MIN_VAL : atof(body.m_price);
			return 0.0;
		}
		double GetTknPriceCalc(const MarketStreamType2Body& body)
		{
			if (IsEmpty(body.m_yield))return MIN_VAL;
			if (atoi(body.m_rebate) != 1)
			{
				double dt = atof(body.m_yield);
				if (atoi(body.m_quotetype) != 3)
				{
					int nIndex = CBondContainer::instance().GetBondIndex(body.m_bondkey, body.m_listedmarket);
					if (CBondContainer::instance().IsValidIndex(nIndex))
					{
						const CBondInfo& bi = CBondContainer::instance().ElementAtR(nIndex);
						if (bi.IsBondABS() || bi.IsTransBond())
						{
							if (dt <= 0.0 || dt >= 30.0)return MIN_VAL;
						}
					}
				}
				return dt;
			}
			return MIN_VAL;
		}
		double GetCleanCleanPrice(const MarketStreamType2Body& body) //成交净价
		{
			/*
			原始代码,要调用ToLineFloat(GetCleanPriceStr(body));
			性能低下
			经过分析,其返回结果与以下逻辑相同
			并且,此文件中返回值,只是用来作为对两条成交记录进行比较,而不是显示
			*/
			if (atoi(body.m_rebate) != 1)
				return IsEmpty(body.m_cleanPrice) ? MIN_VAL : atof(body.m_cleanPrice);
			return 0.0;
		}
		double GetTakenCdc(const MarketStreamType2Body& body , const CBondInfo& info, const int nBondIndex, bool bIsCDCAuthValid)
		{	// 成交-中债,此处值作为显示
			float taken = GetTknPriceCalc(body);
			if (taken < -1000)
				return MIN_VAL;
			taken = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, true, nullptr, taken, false);
			if (taken <= INVALID_CDC_VALUE){
				return MIN_VAL;
			}
			return taken;
		}
		double GetTakenCsi(const MarketStreamType2Body& body, const CBondInfo& info)
		{	// 成交-中债,此处值作为显示

			float taken = GetTknPriceCalc(body);
			if (taken < -1000)
				return MIN_VAL;

			if (taken >= 30.0 || taken == 0.0)
				return _INVALID_CSI_VALUE;

			double dRet = _INVALID_CSI_VALUE;

			xCSIUint_c xUnit;
			if (CBondCSInfo::instance().GetCsiUnit(info.GetCombBondKey(), xUnit))
			{
				double dExercise = xUnit.IsHaveExercise() ? xUnit.m_dYieldToExercise : _INVALID_CSI_VALUE;
				double dMaturity = xUnit.IsHaveMarturity() ? xUnit.m_dYieldToMaturity : _INVALID_CSI_VALUE;

				if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE)
				{
					dExercise = taken - dExercise;
					dMaturity = taken - dMaturity;
					dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
				}
				else if (dExercise > _INVALID_CSI_VALUE)
				{
					dRet = taken - dExercise;
				}
				else if (dMaturity > _INVALID_CSI_VALUE)
				{
					dRet = taken - dMaturity;
				}
			}

			return dRet;
		}
		double GetFISSETakenNetPrice(const MarketStreamType2Body& body)
		{	//上证固收成交净价
			return IsEmpty(body.m_cleanPrice) ? MIN_VAL : atof(body.m_cleanPrice);
		}
		double GetFISSETakenFullPrice(const MarketStreamType2Body& body)
		{	//上证固收成交全价
			return IsEmpty(body.m_fullPrice) ? MIN_VAL : atof(body.m_fullPrice);
		}
		double GetFISSETakenYield(const MarketStreamType2Body& body)
		{	//上证固收成交收益率
			return IsEmpty(body.m_yield) ? MIN_VAL : atof(body.m_yield);
		}
		double GetFISSETakenVolumn(const MarketStreamType2Body& body)
		{	//上证固收成交量
			return IsEmpty(body.m_volume) ? MIN_VAL : atof(body.m_volume);
		}
		double GetFISSETakenAmount(const MarketStreamType2Body& body)
		{	//上证固收成交额，暂存在m_price字段
			return IsEmpty(body.m_price) ? MIN_VAL : atof(body.m_price);
		}
	public:
		virtual void PreGetRecordField(const vector<SortInfo>& orders, int corpid){
			for (int i = 0; i < (int)orders.size(); i++)
			{
				const SortInfo& co = orders[i];
				if (IsRequireCDCAuthority((VSortKey)co.column_id))
				{
					m_cdcauthKey = SSUserAccountManager::instance().GetCDCAutorityKey();
					m_hascdcrights = SSUserAccountManager::instance().HasAnyCDCAuthority();
					break;
				}
			}
		}
		virtual bool GetRecordField(const void* pkey, int col, char* field, int capcity)
		{
			Q_ASSERT(pkey != 0 && m_records);
			// 根据DealIndex获取MarketStreamInfo,然后计算排序比较所需要的字段
			const KeyType& key = *((const KeyType*)pkey);
			const void* precord = m_records->FindRecord(key);
			Q_ASSERT_X(precord, "[STREAM]IRecordMap:0x%8x 中找不到 key:%s", key.id.c_str());
			if (precord == NULL)
				return false;
			const RecordType& record = *((const RecordType*)precord);
			int i = CBondContainer::instance().GetBondIndex(record.m_body.m_bondkey, record.m_body.m_listedmarket);
			const CBondInfo& bi = GetBond(i);
			//不是COL_*,而是SortKey,参考CDlgQuoteV2::GetSortKey和BPMarketTknWnd.cpp的CompareField
			// 只需要处理CBPMarketTknWndV2::GetSortKey中的即可
			// 根据成交记录信息,计算出两条记录比较所需要的字段
			// 具体每列的字段如何计算,参考之前的BPMarketTknWnd.cpp中的BuildSortString和CompareField
			// 此函数获取的字段值,只是用来对两条记录进行比较
			switch (col)
			{
			case VBOND_CODE://COL_CODE
				StringCopy(field, capcity, bi.GetBondCode());
				break;
			case VSHORT_NAME://COL_NAME
				StringCopy(field, capcity, bi.GetBondShortName());
				break;
			case VSHORT_NAME_EN://COL_NAME
				StringCopy(field, capcity, bi.GetBondShortNameEn().c_str());
				break;
			case VEXPIRY_DATE://COL_TTM
			{
				string sRemainDate = bi.GetRemainDate();
				double dDay1 = CBondContainer::CalcRemainingDay(sRemainDate);
				if (sRemainDate.find("D") == string::npos) //365D小于366D小于1Y
				{
					dDay1 += 1.1;
				}
				*((double*)field) = dDay1;
			}
			break;
			case VMODIFY_TIME://kSortTypeDouble,compare_modify_time,COL_UPDATETIME
				*((double*)field) = record.m_modify_time;
				break;
			case VRATING://kSortTypeInt,compare_rating,CompareRankWithIssuerRating,COL_RATE
			case VISSUERRATING:
				*((int*)field) = RatingRankManager::Get().GetRatingRank(bi.GetIssuerRatingEx());
				break;
			case VCDCRATING://kSortTypeInt,compare_rating,CompareRankWithIssuerRating
				if (SSUserAccountManager::instance().HasAuthOfCDC())
					*((int*)field) = RatingRankManager::Get().GetRatingRank(bi.GetCDCRating());
				break;
			case VCSIRATING://kSortTypeInt,compare_rating,CompareRankWithIssuerRating
				if (SSUserAccountManager::instance().HasAuthOfCSI())
					*((int*)field) = RatingRankManager::Get().GetRatingRank(bi.GetCSIRating());
				break;
			case VCBRRATING://kSortTypeInt,compare_rating,CompareRankWithIssuerRating
				if (SSUserAccountManager::instance().HasAuthOfCBR())
					*((int*)field) = RatingRankManager::Get().GetRatingRank(bi.GetCBRRating());
				break;
			case VESTBPRICEPRE://kSortTypeDouble,compare_estb_price;COL_CDCVAL
			{
				int optType;
				*((double*)field) = (bi.IsCDCAuthValid()) ? ToDashFloat(CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, true, i, CBondCDCPriceInfo::price_type_yield, true).c_str()) : MIN_UNAUTH_VALUE;
				break;
			}
			case VESTBPRICETODAY://kSortTypeDouble,compare_estb_price;COL_CDCVAL
			{
				int optType;
				*((double*)field) = (bi.IsCDCAuthValid()) ? ToDashFloat(CBondCDCPriceInfo::instance().GetCDCPriceToday(optType, true, i, CBondCDCPriceInfo::price_type_yield, true).c_str()) : MIN_UNAUTH_VALUE;
				break;
			}
			case VESTBCLEPRICE://kSortTypeDouble,compare_estb_cprice
			{
				int optType;
				*((double*)field) = (bi.IsCDCAuthValid()) ? atof(CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, true, i, CBondCDCPriceInfo::price_type_clean, true).c_str()) : MIN_UNAUTH_VALUE;
				break;
			}
			case VBROKERKEY:
				*((int*)field) = atoi(record.m_company_id);
				break;
			case VBONDRATING:
				*((int*)field) = RatingRankManager::Get().GetRatingRank(bi.GetBondRating());
				break;
			case PLANNED_ISSURE_AMOUNT://compare_planned_issure_amount,计划发行量(亿)
				*((double*)field) = bi.GetPlannedIssueAmount();
				break;
			case BID_LIMIT://kSortTypeBidLimit,compare_bid_limit,投标区间
			{
				const char* strBottom_i = bi.GetBidLimitBottom();
				const char* strTop_i = bi.GetBidLimitTop();
				double dBottom_i = strBottom_i == NULL ? 0 : atof(strBottom_i);
				double dTop_i = strTop_i == NULL ? 0 : atof(strTop_i);
				*((double*)field) = dBottom_i;
				*((double*)field + 1) = dTop_i;
			}break;
			case AUCTION_LIMIT://compare_auction_limit,标位区间
			{
				const char* strBottom_i = bi.GetAuctionFlr();
				const char* strTop_i = bi.GetAuctionCap();
				double dBottom_i = strBottom_i == NULL ? 0 : atof(strBottom_i);
				double dTop_i = strTop_i == NULL ? 0 : atof(strTop_i);
				*((double*)field) = dBottom_i;
				*((double*)field + 1) = dTop_i;
			}break;
			case ISSUE_START_DATE://:kSortTypeInt,compare_issue_start_date,发行日
				*((int*)field) = bi.GetIssueStartDate() ? atoi(bi.GetIssueStartDate()) : 0;
				break;
			case PAYMENT_DATE://kSortTypeInt,compare_payment_date,缴款日
				*((int*)field) = bi.GetPaymentDate() ? atoi(bi.GetPaymentDate()) : 0;
				break;
			case LISTED_DATE://kSortTypeInt,compare_listed_date,上市日
				*((int*)field) = bi.GetPaymentDate() ? atoi(bi.GetListDate()) : 0;
				break;
			case INSTITUTION_TYPE://kSortTypeInt,compare_institution_type,企业类型
				*((int*)field) = GetInstitutionSortId(bi.GetInstitutionType());
				break;
			case ANNOUNCE_DATE://compare_announce_date
				*((int*)field) = bi.GetAnnounceDate() ? atoi(bi.GetAnnounceDate()) : 0;
				break;
			case COUPON_RATE:
			{
				const char* rate = bi.GetCouponRateCurrent();
				*((double*)field) = (!IsEmpty(rate)) ? atof(rate) : (-999);
			}break;
			case MATURITY_TERM_END://compare_MaturityTerm_End,期限m_sMaturityTerm,
			case TERM_TO_MATURITY:
			{
				*((int*)field) = i;
			}
			break;
			case AREA://compare_area,地区
				StringCopy(field, capcity, bi.GetArea());
				break;
			case SECTOR://compare_sector,行业
				StringCopy(field, capcity, bi.GetSwSector());
				break;
			case INTEREST_START_DATE://kSortTypeString,compare_interest_start_date,起息日
				StringCopy(field, capcity, bi.GetInterestStartDate());
				break;
			case kInstitutionName://kSortTypeString,compare_institution_name,机构简称
				StringCopy(field, capcity, bi.GetInstitutionShortName());
				break;
			case kIssueEndTime://kSortTypeString,compare_issue_end_time,截标时间
			{
				const char* start = bi.GetIssueStartDate();
				int len = strlen(start);
				StringCopy(field, capcity, start);
				StringCopy(field + len, capcity - len, bi.GetIssueEndTime());
			}break;
			case kBondGuarantor://kSortTypeDouble,,compare_actual_issure_amount,实际发行量
			case kBondGuarantorEn:
			{
				std::string sName("");
				auto pIssuer = CQBIssuerInfo::instance().GetIssuerInfo(bi.GetWarranter());
				if (pIssuer)
				{
					if(col == kBondGuarantor)
						StringCopy(field, capcity, pIssuer->field((int)kIssuerInfo::Full_Name_C));
					else
						StringCopy(field, capcity, pIssuer->field((int)kIssuerInfo::Full_Name_E));
				}				
				break;
			}
			case kOutstandingAmount://kSortTypeDouble,,compare_actual_issure_amount,实际发行量
				*((double*)field) = bi.GetOutstandingAmount();
				break;
			case kActualIssureAmount://kSortTypeDouble,,compare_actual_issure_amount,实际发行量
				*((double*)field) = bi.GetActualIssueAmount();
				break;
			case kIssuerAmount://kSortTypeDouble,compare_issure_amount发行量:优先取实际发行量，无值时取计划发行量
			{
				double actual = bi.GetActualIssueAmount();
				if ((actual - 0.000) < 1.0f)
					actual = bi.GetPlannedIssueAmount();
				*((double*)field) = actual;
			}break;
			case kCouponType://kSortTypeString,compare_coupon_type,利率方式
				StringCopy(field, capcity, bi.GetCouponTypeName());
				break;
			case kRateType:		// 票面  add  by  lbl 
				StringCopy(field, capcity, bi.GetRateType());
				break;
			case kDuration://kSortTypeDouble,compare_duration,久期
			{
				if (bi.IsCDCAuthValid())
				{
					int optType;
					*((double*)field) = ToDashFloat(CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, true, i, CBondCDCPriceInfo::price_type_duration, true).c_str());
				}
				else
					*((double*)field) = MIN_UNAUTH_VALUE;
			}
			break;
			case kOutlook://kSortTypeString,compare_outlook,展望
				*((int*)field) = bi.GetOutlookLevel();
				break;
			case kInstitutionFullName://kSortTypeString,compare_institution_fullname,发行人机构全称
				StringCopy(field, capcity, bi.GetInstitutionFullName());
				break;
			case ISSUE_DATE_IsuPeriod://kSortTypeInt,compare_issue_start_date_IssuePeriod,发行日,募集时间段
			{
				const char* strDate = bi.GetIssueStartDate();
				*((int*)field) = (strDate == NULL || !IsEmpty(bi.GetIssuePeriod())) ? 0 : atoi(strDate);
			}break;
			case PAYMENT_DATE_IsuPeriod://kSortTypeInt,compare_payment_date_IssuePeriod???,缴款日,募集时间段
			{
				const char* strDate = bi.GetPaymentDate();
				*((int*)field) = (strDate == NULL) ? 0 : atoi(strDate);
			}break;
			case LISTED_DATE_IsuPeriod://kSortTypeInt,compare_listed_date_IssuePeriod,上市日,募集时间段
			{
				const char* strDate = bi.GetListDate();
				*((int*)field) = (strDate == NULL || !IsEmpty(bi.GetIssuePeriod())) ? 0 : atoi(strDate);
			}break;
			case ANNOUNCE_DATE_IsuPeriod://kSortTypeInt,compare_announce_date_IssuePeriod,公告日,募集时间段
			{
				const char* strDate = bi.GetAnnounceDate();
				*((int*)field) = (strDate == NULL || !IsEmpty(bi.GetIssuePeriod())) ? 0 : atoi(strDate);
			}break;
			case INTEREST_DATE_IsuPeriod://kSortTypeString,compare_interest_start_date_IssuePeriod,起息日，募集时间段
				StringCopy(field, capcity, !IsEmpty(bi.GetIssuePeriod()) ? "--" : bi.GetInterestStartDate());
				break;
			case kIssueRate://kSortTypeDouble,compare_issue_rate,发行利率
			{
				const char* pRate = bi.GetIssueRate();
				*((double*)field) = (!IsEmpty(pRate)) ? atof(pRate) : (-999);
			}break;
			case kConvRate://kSortTypeDouble,compare_conversion_rate,质押比例
				*((double*)field) = atof(bi.GetConversionRate());
				break;
			case kTknPrice://compare_clean_price,成交净价,COL_TKN_CLEANPRICE
				*((double*)field) = GetTknPrice(record.m_body);
				//*((double*)field) = m_taken_price_map.GetCleanPrice(key);
				break;
			case kCouponRate://kSortTypeDouble,compare_coupon_rate_ex,票面利率
			{
				const char* pRate = bi.GetCouponRateCurrent();
				*((double*)field) = (!IsEmpty(pRate)) ? atof(pRate) : (-999);
			}break;
			case kCsiVal://kSortTypeDouble,compare_csival,中证估值
				//*((double*)field) = atof(bi.GetCSYield());
				*((double*)field) = 
					SSUserAccountManager::instance().HasAuthOfCSI() ? CBondCSInfo::instance().GetCsiYieldForSort(bi.GetCombBondKey()) : MIN_UNAUTH_VALUE;
				break;
			case kCsiCleanPrice://kSortTypeDouble,compare_csi_clean_price,中证净价
				//*((double*)field) = atof(bi.GetCSCleanPrice());
				*((double*)field) = 
					SSUserAccountManager::instance().HasAuthOfCSI() ? CBondCSInfo::instance().GetCsiCleanPriceForSort(bi.GetCombBondKey()) : MIN_UNAUTH_VALUE;
				break;
			case kCdcCleanPrice://kSortTypeDouble,compare_cdc_clean_price,中债净价
			{
				int optType;
				*((double*)field) = (bi.IsCDCAuthValid()) ? atof(CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, true, i, CBondCDCPriceInfo::price_type_clean, true).c_str()) : MIN_UNAUTH_VALUE;
				break;
			}
			case kOptionType://kSortTypeString,compare_option_type,含权类型
				StringCopy(field, capcity, bi.GetOptionType());
				break;
			case kOptionDate://kSortTypeDouble,compare_option_date,行权日
				*((double*)field) = atof(bi.GetOptionDate());
				break;
			case kCsi_Cdc://kSortTypeDouble,compare_csi_cdc中证-中债
			{
				//*((double*)field) = (m_hascdcrights && m_cdcauthKey.HasKey(bi.GetCdcAuth())) ? ToDashFloat(GetCsi_CdcPrice(i, true)) : MIN_UNAUTH_VALUE;
				bool bRight = bi.IsCDCAuthValid() && SSUserAccountManager::instance().HasAuthOfCSI();
				*((double*)field) = bRight ? ToDashFloat(qb::biz::csi::FmtCSIMinusCDC(&bi, i, true).c_str()/*GetCsi_CdcPrice(i, true)*/) : MIN_UNAUTH_VALUE;
			}break;
			case kCrossMarket://kSortTypeChar,compare_cross_market,跨市场
				*((char*)field) = bi.GetCrossmarket();
				break;
			case kIndustry://kSortTypeString,行业
				StringCopy(field, capcity, bi.GetSwSector());
				break;
			case kIndustryEn://kSortTypeString,行业
				StringCopy(field, capcity, bi.GetSwSector(true));
				break;
			case kRatingAgency://kSortTypeString,评级机构简称
				StringCopy(field, capcity, bi.GetRatingInstitutionShortName());
				break;
			case VBondType://VBondType 债券类型
				*((int*)field) = CBondTypeMap::instance().GetTypeEm(bi.GetBondSubType(), bi.GetEntCor());
				break;
			case VBondIssuer://VBondIssuer 债券发行人
				StringCopy(field, capcity, bi.GetIssuerCode());
				break;
			case kMaturityDate:StringCopy(field, capcity, bi.GetMaturityDate()); break;
			case kMaturityDate_IsuPeriod://
				StringCopy(field, capcity, !IsEmpty(bi.GetIssuePeriod()) ? "" : bi.GetMaturityDate());
				break;
			case kDeal_Cdc:// 成交-中债
				*((double*)field) = (bi.IsCDCAuthValid() /*m_hascdcrights && m_cdcauthKey.HasKey(bi.GetCdcAuth())*/ ) ? GetTakenCdc(record.m_body, bi, i, true) : MIN_UNAUTH_VALUE;
				//*((double*)field) = GetTakenCdc(key, bi);
				break;
			case kDeal_Csi:// 成交-中证
				*((double*)field) = GetTakenCsi(record.m_body, bi);
				//*((double*)field) = GetTakenCsi(key, bi);
				//bi.GetCSYield();
				break;
			case kTknCleanCleanPrice://compare_clean_price,成交净价
				*((double*)field) = GetCleanCleanPrice(record.m_body);
				break;
			case fisse_deal_netprice://上证固收成交净价
				*((double*)field) = GetFISSETakenNetPrice(record.m_body);
				break;
			case fisse_deal_fullprice://上证固收成交全价
				*((double*)field) = GetFISSETakenFullPrice(record.m_body);
					break;
			case fisse_deal_yield://上证固收成交收益率
				*((double*)field) = GetFISSETakenYield(record.m_body);
					break;
			case fisse_deal_volumn://上证固收成交量
				*((double*)field) = GetFISSETakenVolumn(record.m_body);
					break;
			case fisse_deal_amount://上证固收成交额
				*((double*)field) = GetFISSETakenAmount(record.m_body);
					break;
			case kABSBondBaseType://ABS基础资产
			{
				const CABSBondInfo* absinfo = CBondContainer::instance().GetABSBondInfo(i);
				if (absinfo)StringCopy(field, capcity, absinfo->GetBaseTypeString());
				break;
			}
			case kABSBondSeries: //ABS系列
			{
				const CABSBondInfo* absinfo = CBondContainer::instance().GetABSBondInfo(i);
				if (absinfo)StringCopy(field, capcity, absinfo->GetSeriesName());
				break;
			}
			case kABSBondIssuer://ABS发行人
			{
				const CABSBondInfo* absinfo = CBondContainer::instance().GetABSBondInfo(i);
				if (absinfo)StringCopy(field, capcity, absinfo->GetIssuerCode());
				break;
			}
			case kBondMainUnderwriter://主承机构
				StringCopy(field, capcity, bi.GetMainUnderwriters());
				break;
			default:
				return false;
			}
			return true;

		}
	};

	
	////////////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	RealTimeDealSorter::RealTimeDealSorter() :m_record_head_size(sizeof(KeyType*)),
		m_record_size(0), m_buffer(0), m_capcity(0)
	{
		// sizeof(KeyType*)是故意的,CSortBuffer::LoadSortData中,开头将m_record_head_size
		// 大小的内存当作KeyType*
		m_sort_buffer = new detail::CSortBuffer();
		m_bond_reader = new DealRecordReader();
		//m_sort_manager = CBondSortManager::Acquire();
		Q_ASSERT(m_sort_buffer != 0);
	}

#define MEMCATCH(BLOCK) try{BLOCK;}catch(...){\
	log_warning("BLOCK:%s triggered a CMemoryException,NAME=%s",#BLOCK);\
}
#define SAFE_DELETE_PTR(ptr) if(ptr){delete ptr;ptr=nullptr;}
#define SAFE_DELETE_PTR_ARR(ptr) if(ptr){MEMCATCH(delete [] ptr);ptr=nullptr;}

	RealTimeDealSorter::~RealTimeDealSorter()
	{
		SAFE_DELETE_PTR(m_sort_buffer);
		SAFE_DELETE_PTR_ARR(m_buffer);
		SAFE_DELETE_PTR(m_bond_reader);
	}
	int RealTimeDealSorter::CompareIndex(const KeyType& b1, const KeyType& b2)
	{
		int ncount = m_sortinfos.size();
		Q_ASSERT_X(ncount > 0, "CompareIndex", "没有排序列,SetSortInfo");
		Q_ASSERT_X(m_record_size > m_record_head_size,"CompareIndex", "排序记录大小%d <= 主键大小%d");

		int total_size = 2 * m_record_size;
		if (m_buffer == 0 || m_capcity < total_size)
		{
			if (m_buffer)	delete[] m_buffer;
			m_buffer = new char[total_size];
			memset(m_buffer, 0, total_size);
			m_capcity = total_size;
		}

		// 此时使用m_buffer,并没有构造排序记录,而是反复使用两块记录的内存
		int cmp = 0;
		for (int j = 0; j < (int)m_sortinfos.size(); j++)
		{
			SortInfo& si = m_sortinfos[j];
			memset(m_buffer, 0, m_capcity);
			m_bond_reader->GetRecordField(&b1, si.column_id, m_buffer, si.field_bytes);
			m_bond_reader->GetRecordField(&b2, si.column_id, m_buffer + m_record_size, si.field_bytes);
			cmp = si.comparator(m_buffer, m_buffer + m_record_size);
			cmp = si.ascend ? cmp : -cmp;
			if (cmp != 0)
				break;
		}
		return cmp;
	}
	void RealTimeDealSorter::BindCompareMap(const IRecordMap* records, bool bind)
	{
		// 比较两个记录之前,必须要到records表中去根据主键来找到该记录
		Q_ASSERT(records);
		if (m_bond_reader)
		{
			if (bind)
				m_bond_reader->SetDealRecordMap(records);
			else
				m_bond_reader->SetDealRecordMap(NULL);
		}
	}
	RealTimeDealSorter::kOrderChange RealTimeDealSorter::SetSortInfo(const std::vector<ColumnOrder>& orders)
	{
		// 判断是否是反序,同序,还是重新排序
		kOrderChange order_change = kOrderChangeReorder;
		if (orders.size() == m_sortinfos.size())
		{
			int same_count = 0, reverse_count = 0;
			for (int i = 0; i < (int)orders.size(); i++)
			{
				const ColumnOrder& co = orders[i];
				if (co.comlumn == m_sortinfos[i].column_id)
				{
					if (co.ascend == m_sortinfos[i].ascend)
						same_count++;
					else
						reverse_count++;
				}
			}
			if (same_count == orders.size())
				order_change = kOrderChangeSame;
			else if (reverse_count > 0 && reverse_count == orders.size())
				order_change = kOrderChangeReverse;
		}

		m_sortinfos.clear();
		int offset = m_record_head_size;
		for (int i = 0; i < (int)orders.size(); i++)
		{
			FieldInfo fi;
			if (!SortKeyManager::Get().GetFieldInfo(orders[i].comlumn, fi))
				continue;

			SortInfo si;
			si.column_id = orders[i].comlumn;
			si.ascend = orders[i].ascend;
			si.field_bytes = fi.field_bytes;
			si.offset = offset;
			si.comparator = m_sort_buffer->GetComparator(fi.sort_type);
			si.sort_type = fi.sort_type;
			m_sortinfos.push_back(si);
			offset += si.field_bytes;
		}
		m_record_size = offset;
		return order_change;
	}

	void RealTimeDealSorter::Sort(const std::vector<ColumnOrder>& orders, std::vector<DealIndex>& keys, const IRecordMap* records,bool force)
	{
		/*
		对索引passed进行排序,每个索引都在records中能找到
		*/
		kOrderChange order_change = SetSortInfo(orders);
		// 反向可能会有问题,暂时重新排序
		if (order_change == kOrderChangeReverse)
			order_change = kOrderChangeReorder;
		if (keys.size() > 1)
		{
			if ((force || order_change == kOrderChangeReorder) && m_sortinfos.size() > 0)
			{
				m_bond_reader->SetDealRecordMap(records);
				m_sort_buffer->Sort(keys, m_sortinfos, 0 /*ncorpid*/, m_record_size, m_bond_reader);
				m_bond_reader->SetDealRecordMap(NULL);
			}if (order_change == kOrderChangeReverse)
			{
				if (keys.size() > 1)
					std::reverse(keys.begin(), keys.end());
			}
		}
	}


}